#ifndef __World_H_
#define __World_H_

#include <stdio.h>
#include <wchar.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <math.h>
#include <map>
#include <list>
#include <string>

#include <cstdlib>
#include <time.h>

#include "irrlicht.h"

using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

#include "BornedNumber.h"
#include "stringSeparator.h"
#include "Exception.h"
#include "debug.h"

#include "Map.h"
#include "InputReceiver.h"
//#include "Memory.h"
//#include "Hostility.h"

#include "PlayerEntity.h"
#include "NPCEntity.h"

//#define OCTREE_NODE_ID 2
//#define FREECAM_NODE_ID 2

/*!
	This class, despite the name, manage all about the 3D engine Irrlicht, that is the Irrlicht Device, the Scene Manager, the Video Driver, the InputReceiver, the elapsed time between frames, the Initialization, and refreshing the screen.
	This class is a singleton, therefore, the constructor is not public.
*/
class World 
{
	protected:
	static World* world;		/**< the static lone and unique instance of the class. */
	u32 countedTime__;		/**< Used to count elapsed time. */
	u32 elapsedTime__;		/**< Used to count elapsed time. */
	IGUIWindow* wndPlayer__;	/**<Information window concerning the player. */
	IGUIWindow* wndNPC__;		/**<Information window concerning the player. */
	NPCEntity* targeted__;		/**<The NPC targeted by the player.*/

	// Trucs relatifs au moteur
	int win_width__;		/**< Width of window, in pixels. */
	int win_height__;		/**< Heigth of window, in pixels. */
	IrrlichtDevice* idevice__ ;	/**< IrrlichtDevice, from Irrlicht. */
	IVideoDriver* vdriver__ ;	/**< VideoDriver, from Irrlicht. */
	ISceneManager* smgr__ ;		/**< SceneManager, from Irrlicht. */
	ITimer* timer__;		/**< Timer, from Irrlicht. */
	ICameraSceneNode* freeCam__;	/**< the freelook camera. */
	
	double refreshWindowNpcTime__;  /**< permet to calculate the refresh time of the WindowNPC. */
	double MaxWindowNpcTime__;  /**< time between to refresh of the WindowNPC. */

	InputReceiver* input__;		/**< The input receiver. */
	Map* map__;			/**< The Map instance. */

	/*! Called by update(), used to calculate the time between frames. The reset argument can be set to true if a known big amount of time has elapsed since the last frame (when pausing the game or loading a long level for exemple. It is unused for not.). */
	void update_count_time(bool reset=false);
	/*! Called by update(), used to update the entities via the Map's instance. */
	void update_update_entities();
	/*! Called by update(), used to draw things AND flush (refresh) the output on the monitor. */
	void update_draw();
	/*!Called by update(), used to update the player information window. */
	void update_window_Player();
	/*!Called by update(), used to update the Ennemy information window. */
	void update_window_NPC();
	/*! Constructor. Just initializes pointers to 0. */
	World();

	/*! Method to draw waypoints and zones. */
	void draw_waypoints();
	/*! Method to draw rays to entities' seeking targets. */
	void draw_targets();

	public:
	/*! The only way to create/retrieve the singleton's World's instance. It is created if it does not exist yet. */
	static World* getWorld();
	/*! accessor for targeted variable. */
	NPCEntity* getTargeted();
	/*! modificator for targeted variable. */
	void setTargeted(NPCEntity* e);
	/*! Returns the SceneManager. World should be initialized before calling this function. */
	static ISceneManager* getSceneManager();
	/*! Returns the VideoDriver. World should be initialized before calling this function. */
	static IVideoDriver* getVideoDriver();
	/*! Returns the IrrlichtDevice. World should be initialized before calling this function. */
	static IrrlichtDevice* getIrrlichtDevice();
	/*! Returns the free look camera. World should be initialized before calling this function. */
	static ICameraSceneNode* getFreeCamera();
	/*! Returns the Map. World should be initialized before calling this function. */
	static Map* getMap();
	/*! Returns the Input Receiver. World should be initialized before calling this function. */
	static InputReceiver* getInputReceiver();
	/*! Destructor. Should delete every thing. Also initialize the static World* World::world to 0. */
	virtual ~World();

	/*! Initialize Irrlicht with the width, height and fullscreen parameters. */
	void Init(int width, int height, bool fullscreen);
	/*! Read the configuration file given in argument, then call Init(int, int, bool) with reaed arguments. */
	void Init(const irr::core::string<c8>& configfile);
	/*!Init the player information window. */
	void InitWindowPlayer();
	/*!Init the NPC information window. */
	void InitWindowNPC();
	/*! Returns the elapsed time since last frame in milliseconds. */
	virtual double elapsedTime();
	/*! Updates everything, but does not refresh the screen if elapsed time is 0. */
	virtual bool update();

	/*! Returns a float between 0 and 1. */
	static float randf();

};

#endif

